import * as React from 'react';
import { connect } from 'react-redux';
import { message, Form, Collapse, Button, Row, Col, Modal, Spin } from 'antd';
import { get, map, partial, invoke } from 'lodash';

import { getPanelOptions } from 'components/common/collapse';

import { removeAssist, fetchAssistDetail, createAssist, updateAssist } from 'actions/assist';

import { isLoading } from 'utils/utils';
import ACTIONS from 'constants/assist';

import LoadableComponent from 'components/common/LoadableComponent';
const LoadableBasicEdit = LoadableComponent(() => import('pages/knowledge/EditBasic'));

// 不能使用无状态LoadableComponent组件加载，无法传递ref
import EditImage from 'pages/knowledge/EditImage';
import EditAudio from 'pages/knowledge/EditAudio';

interface EditProps {
  dispatch: (action: any) => any;
  handleNewCallback: (id: number) => any;
  handleRemoveCallback: () => any;
  form: any;
  assistId: number;
  loadingGroup: any;
}

interface EditState {
  activeKey: string[];
  editAssist: any;
  audio: any;
  cover: any;
}

/**
 * Assist新增或修改
 */
class Edit extends React.Component<EditProps, EditState> {
  RefEditAudio: any;
  RefEditImage: any;
  static collapseKeys = ['basic', 'tags', 'audio', 'images'];
  static defaultProps: EditProps = {
    dispatch: () => {},
    handleNewCallback: () => {},
    handleRemoveCallback: () => {},
    form: {},
    assistId: 0,
    loadingGroup: {},
  };

  constructor(props: EditProps) {
    super(props);
    this.state = {
      activeKey: Edit.collapseKeys,
      editAssist: null,
      audio: null,
      cover: null,
    };
  }

  componentDidMount() {
    const { assistId } = this.props;
    if (assistId) {
      this.handleFetchDetail(assistId, () => {
        this.handleSwitchCollapse(Edit.collapseKeys);
      });
    }
  }

  componentWillReceiveProps(nextProps: any) {
    const { assistId } = nextProps;
    const { assistId: oldAssistId } = this.props;

    if (oldAssistId !== assistId) {
      if (assistId) {
        this.handleFetchDetail(assistId);
      } else {
        this.setState({
          editAssist: null,
          audio: null,
          cover: null,
        });
      }
    }
  }

  handleFetchDetail = (assistId: number = this.props.assistId, callback: any = () => {}) => {
    const { dispatch } = this.props;

    dispatch(fetchAssistDetail(assistId)).then((result: any) => {
      const { code, msg, response } = result;
      if (code) {
        message.error(msg);
      } else {
        this.setState(
          {
            editAssist: response.data,
            audio: get(response.data, 'audio', null),
            cover: get(response.data, 'cover', null),
          },
          () => {
            callback();
          }
        );
      }
    });
  };

  handleRemove = () => {
    const { dispatch, assistId, loadingGroup, handleRemoveCallback } = this.props;

    if (assistId && !isLoading(loadingGroup, ACTIONS.REMOVE)) {
      Modal.confirm({
        title: '危险',
        content: '你确定要删除此辅助词及相关数据吗？',
        okText: '确定',
        cancelText: '取消',
        iconType: 'info-circle',
        onOk: () => {
          dispatch(removeAssist(assistId)).then((result: any) => {
            if (result.code) {
              message.error(result.msg);
            } else {
              message.success('辅助词删除成功');
              handleRemoveCallback();
            }
          });
        },
      });
    }
  };

  handleSwitchCollapse = (activeKey: string[], callback = () => {}) => {
    this.setState(
      {
        activeKey,
      },
      callback
    );
  };

  // 封面图片回调
  handleCoverCallback = (covers: any[]) => {
    this.setState({
      cover: covers[0],
    });
  };

  // 音频回调
  handleAudioCallback = (audio: any) => {
    this.setState({
      audio,
    });
  };

  handleSubmit = (e: any) => {
    e.preventDefault();

    const { loadingGroup, form, dispatch, handleNewCallback } = this.props;
    const { editAssist, audio, cover } = this.state;

    const loadingKey = editAssist ? ACTIONS.UPDATE : ACTIONS.CREATE;

    if (isLoading(loadingGroup, loadingKey)) {
      return;
    }

    form.validateFields((error: any, values: Record<string, any>) => {
      if (error) return;

      if (!audio) {
        message.error('音频不能为空');
        return;
      }

      values = {
        ...values,
        audioId: audio.id,
      };

      if (cover) {
        values = {
          ...values,
          coverId: cover.id,
        };
      }

      const action = editAssist ? updateAssist(editAssist.id, values) : createAssist(values);

      dispatch(action).then((result: any) => {
        if (result.code) {
          message.error(result.msg);
        } else {
          message.success('保存成功');

          // 新增回调
          if (!editAssist) {
            handleNewCallback(result.response.data);
          }
        }
      });
    });
  };

  render() {
    const { loadingGroup, assistId, form } = this.props;
    const { activeKey, editAssist, audio, cover } = this.state;
    const loadingKey = editAssist ? ACTIONS.UPDATE : ACTIONS.CREATE;

    const collapseOptions: any = {
      activeKey,
      bordered: false,
      onChange: this.handleSwitchCollapse,
    };

    return (
      <div>
        <Spin spinning={isLoading(loadingGroup, ACTIONS.FETCH)} tip="Loading...">
          <Form onSubmit={this.handleSubmit}>
            <Collapse {...collapseOptions}>
              <Collapse.Panel header="基本信息" key={Edit.collapseKeys[0]}>
                <LoadableBasicEdit form={form} editWord={editAssist} />
              </Collapse.Panel>
              <Collapse.Panel
                {...getPanelOptions(1, '音频', {
                  key: Edit.collapseKeys[2],
                  addButton: true,
                  onAdd: partial(invoke, this, 'RefEditAudio.addAudio'),
                })}>
                <EditAudio
                  handleCallback={this.handleAudioCallback}
                  audio={audio}
                  ref={(EditAudio: any) => {
                    this.RefEditAudio = EditAudio;
                  }}
                />
              </Collapse.Panel>
              <Collapse.Panel
                {...getPanelOptions(1, '卡片图片', {
                  key: Edit.collapseKeys[3],
                  addButton: true,
                  notMust: true,
                  onAdd: partial(invoke, this, 'RefEditImage.addImage'),
                })}>
                <EditImage
                  handleCallback={this.handleCoverCallback}
                  covers={cover ? [cover] : []}
                  selectMax={1}
                  ref={(EditImage: any) => {
                    this.RefEditImage = EditImage;
                  }}
                />
              </Collapse.Panel>
            </Collapse>
            <Row align="middle" type="flex" justify="space-between" style={{ marginTop: 12 }}>
              <Col span={4}>
                <Button
                  size="large"
                  type="primary"
                  htmlType="submit"
                  icon="save"
                  loading={isLoading(loadingGroup, loadingKey)}>
                  提交
                </Button>
              </Col>
              <Col span={4} style={{ textAlign: 'right' }}>
                <Button
                  type="primary"
                  className="ant-btn-danger"
                  onClick={this.handleRemove}
                  size="large"
                  disabled={!assistId}
                  icon="delete">
                  删除
                </Button>
              </Col>
            </Row>
          </Form>
        </Spin>
      </div>
    );
  }
}

interface OwnProps {
  assistId: number;
  handleNewCallback: (id: number) => any;
  handleRemoveCallback: () => any;
}

function mapStateToProps(state: any, ownProps: OwnProps) {
  const { loadingGroup } = state;
  const { assistId, handleNewCallback } = ownProps;

  return {
    loadingGroup,
    assistId,
    handleNewCallback,
  };
}

export default connect(mapStateToProps)(Form.create()(Edit));
